home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / magplip / source / device.c < prev    next >
C/C++ Source or Header  |  1995-08-20  |  24KB  |  756 lines

  1. /*
  2. ** $VER: device.c 1.7 (20 Aug 1995)
  3. **
  4. ** magplip.device - Parallel Line Internet Protocol
  5. **
  6. ** Original code written by Oliver Wagner and Michael Balzer.
  7. **
  8. ** This version has been completely reworked by Marius Gröger, introducing
  9. ** slight protocol changes. The new source is a lot better organized and
  10. ** maintainable.
  11. **
  12. ** Additional changes and code cleanup by Jan Kratochvil and Martin Mares.
  13. ** The new source is significantly faster and yet better maintainable.
  14. **
  15. ** (C) Copyright 1993-1994 Oliver Wagner & Michael Balzer
  16. ** (C) Copyright 1995 Marius Gröger
  17. ** (C) Copyright 1995 Jan Kratochvil & Martin Mares
  18. **     All Rights Reserved
  19. **
  20. ** $HISTORY:
  21. **
  22. ** 20 Aug 1995 : 001.007 :  just bumped for new header, no code changes
  23. ** 05 Aug 1995 : 001.006 :  finally compiles w/out warnings :)
  24. ** 25 Apr 1995 : 001.005 :  now compiles with ANSI and STRICT
  25. ** 08 Mar 1995 : 001.004 :  now handles directly write reqs, the server
  26. **                          task is just signalled
  27. ** 05 Mar 1995 : 001.003 :  S2_DEVICEQUERY was desastrously broken
  28. ** 04 Mar 1995 : 001.002 :  using SANA2IOF_QUICK instead IOF_QUICK
  29. ** 18 Feb 1995 : 001.001 :  using BASEPTR
  30. **                          PLIPBase is cleared in DevInit()
  31. **                          now rejects all r/w-requests without BuffMgmt
  32. ** 12 Feb 1995 : 001.000 :  reworked original
  33. */
  34.  
  35. #define DEBUG 0
  36.  
  37. /*F*/ /* includes */
  38. #ifndef CLIB_ALIB_PROTOS_H
  39. #include <clib/alib_protos.h>
  40. #endif
  41. #ifndef CLIB_EXEC_PROTOS_H
  42. #include <clib/exec_protos.h>
  43. #include <pragmas/exec_sysbase_pragmas.h>
  44. #endif
  45. #ifndef CLIB_DOS_PROTOS_H
  46. #include <clib/dos_protos.h>
  47. #include <pragmas/dos_pragmas.h>
  48. #endif
  49. #ifndef CLIB_CIA_PROTOS_H
  50. #include <clib/cia_protos.h>
  51. #include <pragmas/cia_pragmas.h>
  52. #endif
  53. #ifndef CLIB_MISC_PROTOS_H
  54. #include <clib/misc_protos.h>
  55. #include <pragmas/misc_pragmas.h>
  56. #endif
  57. #ifndef CLIB_UTILITY_PROTOS_H
  58. #include <clib/utility_protos.h>
  59. #include <pragmas/utility_pragmas.h>
  60. #endif
  61. #ifndef CLIB_TIME_PROTOS_H
  62. #include <clib/timer_protos.h>
  63. #include <pragmas/timer_pragmas.h>
  64. #endif
  65. #ifndef DEVICES_SANA2_H
  66. #include <devices/sana2.h>
  67. #endif
  68.  
  69. #ifndef HARDWARE_CIA_H
  70. #include <hardware/cia.h>
  71. #endif
  72.  
  73. #ifndef DOS_DOSTAGS_H
  74. #include <dos/dostags.h>
  75. #endif
  76.  
  77. #ifndef RESOURCES_MISC_H
  78. #include <resources/misc.h>
  79. #endif
  80.  
  81. #ifndef EXEC_MEMORY_H
  82. #include <exec/memory.h>
  83. #endif
  84.  
  85. #ifndef _STRING_H
  86. #include <string.h>
  87. #endif
  88.  
  89. #ifndef __MAGPLIP_H
  90. #include "magplip.h"
  91. #endif
  92.  
  93. #ifndef __DEBUG_H
  94. #include "debug.h"
  95. #endif
  96. /*E*/
  97.  
  98. /*F*/ /* imports */
  99. extern VOID SAVEDS ServerTask(VOID);
  100. extern BOOL remtracktype(BASEPTR, ULONG type);
  101. extern BOOL addtracktype(BASEPTR, ULONG type);
  102. extern BOOL gettrackrec(BASEPTR, ULONG type, APTR info);
  103. extern VOID dotracktype(BASEPTR, ULONG type, ULONG ps, ULONG pr, ULONG bs, ULONG br, ULONG pd);
  104. extern VOID freetracktypes(BASEPTR);
  105. #define min __builtin_min
  106. /*E*/
  107. /*F*/ /* exports */
  108. extern ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase);
  109. extern ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR);
  110. extern ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR);
  111. extern ASM SAVEDS BPTR DevClose( REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  112. extern VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2);
  113. extern ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR);
  114. extern ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  115. /*E*/
  116. /*F*/ /* statics */
  117. static BOOL isinlist(struct Node *n, struct List *l);
  118. static VOID abort(BASEPTR, struct IOSana2Req *ior);
  119. /*E*/
  120.  
  121.    /*
  122.    ** various support routines
  123.    */
  124. /*F*/ static BOOL isinlist(struct Node *n, struct List *l)
  125. {
  126.    struct Node *cmp;
  127.  
  128.    for(cmp = l->lh_Head; cmp->ln_Succ; cmp = cmp->ln_Succ)
  129.       if (cmp == n) return TRUE;
  130.    
  131.    return FALSE;
  132. }
  133. /*E*/
  134. /*F*/ static VOID abort(BASEPTR, struct IOSana2Req *ior)
  135. {
  136.    Remove((struct Node*)ior);
  137.    ior->ios2_Req.io_Error = IOERR_ABORTED;
  138.    ior->ios2_WireError = 0;
  139.    ReplyMsg((struct Message*)ior);
  140. }
  141. /*E*/
  142.  
  143.    /*
  144.    ** initialise device
  145.    */
  146. /*F*/ extern ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase)
  147. {
  148.    BOOL ok;
  149.    UBYTE *p;
  150.    UWORD i;
  151.  
  152.    d(("entered device, initialising PLIPBase...\n"));
  153.  
  154.       /* clear data base */
  155.    for(p = ((UBYTE*)pb) + sizeof(struct Library), i = sizeof(struct PLIPBase)-sizeof(struct Library); i; i--)
  156.       *p++ = 0;
  157.  
  158.    SysBase = _SysBase;
  159.  
  160.    pb->pb_SegList = seglist;           /* store DOS segment list */
  161.  
  162.       /* init some default values */
  163.    pb->pb_MTU = PLIP_DEFMTU;
  164.    pb->pb_ReportBPS = PLIP_DEFBPS;
  165.    pb->pb_Retries = PLIP_DEFRETRIES;
  166.    pb->pb_Flags = PLIPF_NOTCONFIGURED | PLIPF_OFFLINE;
  167.    pb->pb_Timeout = PLIP_DEFTIMEOUT;
  168.  
  169.       /* set signal to unallocated state */
  170.    pb->pb_IntSig = (ULONG)-1;
  171.  
  172.       /* initialise the lists */
  173.    NewList((struct List*)&pb->pb_ReadList);
  174.    NewList((struct List*)&pb->pb_WriteList);
  175.    NewList((struct List*)&pb->pb_EventList);
  176.    NewList((struct List*)&pb->pb_ReadOrphanList);
  177.    NewList((struct List*)&pb->pb_TrackList);
  178.    NewList((struct List*)&pb->pb_BufferManagement);
  179.  
  180.       /* initialise the access protection semaphores */
  181.    InitSemaphore(&pb->pb_ReadListSem);
  182.    InitSemaphore(&pb->pb_ReadOrphanListSem);
  183.    InitSemaphore(&pb->pb_EventListSem);
  184.    InitSemaphore(&pb->pb_WriteListSem);
  185.    InitSemaphore(&pb->pb_TrackListSem);
  186.    InitSemaphore(&pb->pb_Lock);
  187.  
  188.    ok = FALSE;
  189.  
  190.    if (UtilityBase = OpenLibrary("utility.library", 37))
  191.    {
  192.       if (DOSBase = OpenLibrary("dos.library", 37))
  193.       {
  194.          ok = TRUE;
  195.       }
  196.       else
  197.       {
  198.          d(("no dos\n"));
  199.       }
  200.  
  201.       if (!ok) CloseLibrary(UtilityBase);
  202.    }
  203.    else
  204.    {
  205.       d(("no utility\n"));
  206.    }
  207.  
  208.    d(("left %ld\n",ok));
  209.  
  210.    return (struct Device *)(ok ? pb : NULL);
  211. }
  212. /*E*/
  213.  
  214.    /*
  215.    ** open device
  216.    */
  217. /*F*/ extern ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR)
  218. {
  219.    BOOL ok = FALSE;
  220.    struct BufferManagement *bm;
  221.    LONG rv;
  222.  
  223.    d(("entered\n"));
  224.  
  225.    /* Make sure our open remains single-threaded. */
  226.    ObtainSemaphore(&pb->pb_Lock);
  227.  
  228.    pb->pb_DevNode.lib_OpenCnt++;
  229.  
  230.    /* not promiscouos mode and unit valid ? */
  231.    if (!(flags & SANA2OPF_PROM) && ((unit == 0) || (unit == 1)))
  232.    {
  233.       /* Allow access only if NOT:
  234.       **
  235.       **    Anybody else has already opened it AND
  236.       **          the current access is exclusive
  237.       **       OR the first access was exclusive
  238.       **       OR first access was A, current wants B
  239.       **       OR first access was B, current wants A
  240.       */
  241.  
  242.       if (!((pb->pb_DevNode.lib_OpenCnt > 1) &&
  243.             ((flags & SANA2OPF_MINE)
  244.           || (pb->pb_Flags & PLIPF_EXCLUSIVE)
  245.           || (unit && !(pb->pb_Flags & PLIPF_SIDEA))
  246.           || (!unit && (pb->pb_Flags & PLIPF_SIDEA)))))
  247.       {
  248.          if (flags & SANA2OPF_MINE)
  249.             pb->pb_Flags |= PLIPF_EXCLUSIVE;
  250.          else
  251.             pb->pb_Flags &= ~PLIPF_EXCLUSIVE;
  252.          
  253.          /*
  254.          ** The origninal "client/server" scheme was unfortune. I guess this
  255.          ** resulted out of the (also very unfortune) wiring: POUT->POUT,
  256.          ** BUSY->BUSY. Had the creators chosen this connection to be crossed
  257.          ** over, a completely symmetrical driver would have been possible.
  258.          ** My new approach does the (in either case) neccessary crossing
  259.          ** by software. The PLIPBase->HandshakeXXX[] arrays are initialised
  260.          ** here so that the actual communication code are no longer bothered.
  261.          */
  262.          if (unit)
  263.          {
  264.             pb->pb_Flags |= PLIPF_SIDEA;
  265.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRPOUT;
  266.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRBUSY;
  267.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRPOUT;
  268.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRBUSY;
  269.          }
  270.          else
  271.          {
  272.             pb->pb_Flags &= ~PLIPF_SIDEA;
  273.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRBUSY;
  274.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRPOUT;
  275.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRBUSY;
  276.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRPOUT;
  277.          }
  278.  
  279.          /*
  280.          ** Each opnener get's it's own BufferManagement. This is neccessary
  281.          ** since we want to allow several protocol stacks to use PLIP
  282.          ** simultaneously.
  283.          */
  284.          if (bm = AllocVec(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  285.          {
  286.             /*
  287.             ** We don't care if there really are buffer management functions,
  288.             ** because there might be openers who just want some statistics
  289.             ** from us.
  290.             **
  291.             ** The type casting below is very beautiful. I don't know whether this
  292.             ** is a SAS/C bug, or ANSI-C: However I have to cast the ULONG that I
  293.             ** got from GetTagData() to a (void (*)(void)) function pointer. Now
  294.             ** I may cast it to (BMFunc), which defines the __asm and register stuff.
  295.             */
  296.             bm->bm_CopyToBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyToBuff, NULL,
  297.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  298.             bm->bm_CopyFromBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyFromBuff, NULL,
  299.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  300.  
  301.             d(("starting servertask\n"));
  302.             if (!pb->pb_Server)
  303.             {
  304.                struct ServerStartup ss;
  305.                struct MsgPort *port;
  306.  
  307.                if (port = CreateMsgPort())
  308.                {
  309.                   d(("starting server"));
  310.                   if (pb->pb_Server = CreateNewProcTags(NP_Entry, ServerTask, NP_Name, SERVERTASKNAME))
  311.                   {
  312.                      ss.ss_PLIPBase = pb;
  313.                      ss.ss_Msg.mn_Length = sizeof(ss);
  314.                      ss.ss_Msg.mn_ReplyPort = port;
  315.                      d(("passing off startup msg, pb is %lx\n", pb));
  316.                      PutMsg(&pb->pb_Server->pr_MsgPort, (struct Message*)&ss);
  317.                      WaitPort(port);
  318.  
  319.                      ok = TRUE;
  320.                   }
  321.                   else
  322.                   {
  323.                      d(("couldn't launch server task\n"));
  324.                   }
  325.                   DeleteMsgPort(port);
  326.                }
  327.                else
  328.                {
  329.                   d(("no temp-message port for server startup\n"));
  330.                }
  331.             }
  332.             else ok = TRUE;
  333.  
  334.             if (!ok)
  335.                FreeVec(bm);
  336.             else
  337.             {
  338.                /* enqueue buffer management into list
  339.                */
  340.                AddTail((struct List *)&pb->pb_BufferManagement,(struct Node *)bm);
  341.                pb->pb_DevNode.lib_OpenCnt++;
  342.                pb->pb_DevNode.lib_Flags &= ~LIBF_DELEXP;
  343.                ios2->ios2_BufferManagement = (VOID *)bm;
  344.                ios2->ios2_Req.io_Error = 0;
  345.                ios2->ios2_Req.io_Unit = (struct Unit *)unit;
  346.                ios2->ios2_Req.io_Device = (struct Device *)pb;
  347.                rv = 0;
  348.             }
  349.          }
  350.       }
  351.    }
  352.  
  353.       /* See if something went wrong. */
  354.    if(!ok)
  355.    {
  356.       ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  357.       ios2->ios2_Req.io_Unit = (struct Unit *) 0;
  358.       ios2->ios2_Req.io_Device = (struct Device *) 0;
  359.       rv = IOERR_OPENFAIL;
  360.    }
  361.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  362.  
  363.    pb->pb_DevNode.lib_OpenCnt--;
  364.    ReleaseSemaphore(&pb->pb_Lock);
  365.  
  366.    return rv;
  367. }
  368. /*E*/
  369.  
  370.    /*
  371.    ** close device
  372.    */
  373. /*F*/ extern ASM SAVEDS BPTR DevClose(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  374. {
  375.    BPTR seglist;
  376.    struct BufferManagement *bm;
  377.  
  378.    d2(("entered\n"));
  379.  
  380.    ObtainSemaphore(&pb->pb_Lock);
  381.  
  382.       /* invalidate IO request block */
  383.    ior->ios2_Req.io_Device = (struct Device *)-1;
  384.    ior->ios2_Req.io_Unit = (struct Unit *)-1;
  385.  
  386.       /* search and free BuffMgmt structure */
  387.    for(bm = (struct BufferManagement *)pb->pb_BufferManagement.lh_Head;
  388.        bm->bm_Node.mln_Succ; bm = (struct BufferManagement *)bm->bm_Node.mln_Succ)
  389.       if (bm == ior->ios2_BufferManagement)
  390.       {
  391.          Remove((struct Node*)bm);
  392.          FreeVec(bm);
  393.          break;
  394.       }
  395.  
  396.    pb->pb_DevNode.lib_OpenCnt--;
  397.  
  398.    ReleaseSemaphore(&pb->pb_Lock);
  399.  
  400.    if (pb->pb_DevNode.lib_Flags & LIBF_DELEXP)
  401.       seglist = DevExpunge(pb);
  402.    else
  403.       seglist = 0;
  404.  
  405.    return seglist;
  406. }
  407. /*E*/
  408. /*F*/ extern ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR)
  409. {
  410.    BPTR seglist;
  411.    ULONG sigb;
  412.  
  413.    d2(("entered\n"));
  414.  
  415.    if (pb->pb_DevNode.lib_OpenCnt)
  416.    {
  417.       pb->pb_DevNode.lib_Flags |= LIBF_DELEXP;
  418.       seglist = 0;
  419.    }
  420.    else
  421.    {
  422.          /* detach device from system list */
  423.       Remove((struct Node*)pb);
  424.  
  425.          /* stop the servr task */
  426.       d2(("killing server task\n"));
  427.       pb->pb_Task = FindTask(0L);
  428.          /* We must allocate a new signal, as we don't know in whose
  429.          ** context we're running. If we get no signal, we poll
  430.          ** for the server-exits flag.
  431.          */
  432.       sigb = AllocSignal(-1);
  433.       pb->pb_ServerStoppedSigMask = (sigb == -1) ? 0 : (1<<sigb);
  434.       Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_C);
  435.       if (pb->pb_ServerStoppedSigMask)
  436.          Wait(pb->pb_ServerStoppedSigMask);
  437.       else
  438.       {
  439.          while(!(pb->pb_Flags & PLIPF_SERVERSTOPPED))
  440.             Delay(10);
  441.       }
  442.       d2(("server task has gone\n"));
  443.  
  444.          /* clean up track */
  445.       freetracktypes(pb);
  446.  
  447.       CloseLibrary(UtilityBase);
  448.       CloseLibrary(DOSBase);
  449.  
  450.          /* save seglist for return value */
  451.       seglist = (long)pb->pb_SegList;
  452.  
  453.          /* return memory
  454.          **
  455.          ** NO FURTHER ACCESS TO PLIPBase ALLOWED!
  456.          */
  457.       FreeMem( ((char *) pb) - pb->pb_DevNode.lib_NegSize,
  458.          (ULONG)(pb->pb_DevNode.lib_PosSize + pb->pb_DevNode.lib_NegSize));
  459.    }
  460.  
  461.    return seglist;
  462. }
  463. /*E*/
  464.  
  465.    /*
  466.    ** initiate io command (1st level dispatcher)
  467.    */
  468. /*F*/ static INLINE VOID DevForwardIO(BASEPTR, struct IOSana2Req *ios2)
  469. {
  470.    d(("forwarding request %ld\n", ios2->ios2_Req.io_Command));
  471.  
  472.    /* request is no longer of type "quick i/o" */
  473.    ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  474.    PutMsg(pb->pb_ServerPort, (struct Message*)ios2);
  475. }
  476. /*E*/
  477. /*F*/ extern VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2)
  478. {
  479.    d(("cmd = %ld, error = %ld, wireerror = %ld\n", ios2->ios2_Req.io_Command, ios2->ios2_Req.io_Error,ios2->ios2_WireError));
  480.  
  481.                   /* if this command was done asynchonously, we must
  482.                   ** reply the request
  483.                   */
  484.    if(!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK))
  485.       ReplyMsg((struct Message *)ios2);
  486.    else           /* otherwise just mark it as done */
  487.       ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  488. }
  489. /*E*/
  490. /*F*/ extern ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR)
  491. {
  492.       /* mark request as active */
  493.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  494.    ios2->ios2_Req.io_Error = S2ERR_NO_ERROR;
  495.    ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  496.  
  497.    d(("cmd = %ld\n",ios2->ios2_Req.io_Command));
  498.  
  499.       /*
  500.       ** 1st level command dispatcher
  501.       **
  502.       ** Here we decide wether we can process the request immediately avoiding
  503.       ** a task switch. This is called "Quick I/O" and signalled to DoIO()
  504.       ** by setting the node type of the request to NT_REPLYMSG (see TermIO()).
  505.       **
  506.       ** Otherwise, we clear the SANA2IOF_QUICK flag and forward the request to
  507.       ** the server. We may NEVER again access the request structure after
  508.       ** the PutMsg()! The server - running at a high priority - will peempt
  509.       ** us and might complety satisfy the request before we will be wakened up
  510.       ** again.
  511.       ** The same goes for those requests that we put into the server's queue.
  512.       */
  513.    switch(ios2->ios2_Req.io_Command)
  514.    {
  515.       case CMD_READ:
  516.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  517.          {
  518.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  519.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  520.          }
  521.          else if (ios2->ios2_BufferManagement == NULL)
  522.          {
  523.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  524.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  525.          }
  526.          else
  527.          {
  528.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  529.             ObtainSemaphore(&pb->pb_ReadListSem);
  530.             AddTail((struct List*)&pb->pb_ReadList, (struct Node*)ios2);
  531.             ReleaseSemaphore(&pb->pb_ReadListSem);
  532.             ios2 = NULL;
  533.          }
  534.       break;
  535.  
  536.       case CMD_WRITE:
  537.       case S2_BROADCAST:
  538.          if (ios2->ios2_Req.io_Flags & SANA2IOF_RAW)
  539.          {
  540.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  541.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  542.          }
  543.          else if(ios2->ios2_DataLength > pb->pb_MTU)
  544.          {
  545.             ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  546.          }
  547.          else if (ios2->ios2_BufferManagement == NULL)
  548.          {
  549.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  550.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  551.          }
  552.          else if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  553.          {
  554.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  555.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  556.          }
  557.          else
  558.          {
  559.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  560.             ios2->ios2_Req.io_Error = 0;
  561.             ObtainSemaphore(&pb->pb_WriteListSem);
  562.             AddTail((struct List*)&pb->pb_WriteList, (struct Node*)ios2);
  563.             ReleaseSemaphore(&pb->pb_WriteListSem);
  564.             Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_F);
  565.             ios2 = NULL;
  566.          }
  567.       break;
  568.  
  569.       case S2_ONLINE:
  570.       case S2_OFFLINE:
  571.       case S2_CONFIGINTERFACE:   /* forward request */
  572.          DevForwardIO(pb, ios2);
  573.          ios2 = NULL;
  574.       break;
  575.  
  576.       case S2_GETSTATIONADDRESS:
  577.          memset(ios2->ios2_DstAddr, 0, SANA2_MAX_ADDR_BYTES);
  578.          memset(ios2->ios2_SrcAddr, 0, SANA2_MAX_ADDR_BYTES);
  579.          ios2->ios2_SrcAddr[0] = ios2->ios2_DstAddr[0] = (pb->pb_Flags & PLIPF_SIDEA) ? 1<<7 : 0;
  580.       break;
  581.          
  582.       case S2_DEVICEQUERY:
  583.       {
  584.          struct Sana2DeviceQuery *devquery;
  585.  
  586.          devquery = ios2->ios2_StatData;
  587.          devquery->DevQueryFormat = 0;        /* "this is format 0" */
  588.          devquery->DeviceLevel = 0;           /* "this spec defines level 0" */
  589.          
  590.          if (devquery->SizeAvailable >= 18) devquery->AddrFieldSize = 1;
  591.          if (devquery->SizeAvailable >= 22) devquery->MTU           = pb->pb_MTU;
  592.          if (devquery->SizeAvailable >= 26) devquery->BPS           = pb->pb_ReportBPS;
  593.          if (devquery->SizeAvailable >= 30) devquery->HardwareType  = S2WireType_PLIP;
  594.          
  595.          devquery->SizeSupplied = min((int)devquery->SizeAvailable, 30);
  596.       }
  597.       break;
  598.          
  599.       case S2_ONEVENT:
  600.          /* Two special cases. S2EVENT_ONLINE and S2EVENT_OFFLINE are supposed to
  601.             retun immediately if we are already in the state that they are waiting
  602.             for. */
  603.          if (((ios2->ios2_WireError & S2EVENT_ONLINE) && !(pb->pb_Flags & PLIPF_OFFLINE)) ||
  604.              ((ios2->ios2_WireError & S2EVENT_OFFLINE) && (pb->pb_Flags & PLIPF_OFFLINE)))
  605.          {
  606.             ios2->ios2_Req.io_Error = 0;
  607.             ios2->ios2_WireError &= (S2EVENT_ONLINE|S2EVENT_OFFLINE);
  608.             DevTermIO(pb,ios2);
  609.             ios2 = NULL;
  610.          }
  611.          else if ((ios2->ios2_WireError & (S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|
  612.                                S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE|S2EVENT_SOFTWARE))
  613.                   != ios2->ios2_WireError)
  614.          {
  615.             /* we cannot handle such events */
  616.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  617.             ios2->ios2_WireError = S2WERR_BAD_EVENT;
  618.          }
  619.          else
  620.          {
  621.             /* Queue anything else */
  622.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  623.             ObtainSemaphore(&pb->pb_EventListSem);
  624.             AddTail((struct List*)&pb->pb_EventList, (struct Node*)ios2);
  625.             ReleaseSemaphore(&pb->pb_EventListSem);
  626.             ios2 = NULL;
  627.          }
  628.       break;
  629.  
  630.       /* --------------- stats support ----------------------- */
  631.  
  632.       case S2_TRACKTYPE:
  633.          if (!addtracktype(pb, ios2->ios2_PacketType))
  634.          {
  635.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  636.             ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
  637.          }
  638.       break;
  639.  
  640.       case S2_UNTRACKTYPE:
  641.          if (!remtracktype(pb, ios2->ios2_PacketType))
  642.          {
  643.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  644.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  645.          }
  646.       break;
  647.  
  648.       case S2_GETTYPESTATS:
  649.          if (!gettrackrec(pb, ios2->ios2_PacketType, ios2->ios2_StatData))
  650.          {
  651.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  652.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  653.          }
  654.       break;
  655.  
  656.       case S2_READORPHAN:
  657.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  658.          {
  659.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  660.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  661.          }
  662.          else if (ios2->ios2_BufferManagement == NULL)
  663.          {
  664.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  665.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  666.          }
  667.          else
  668.          {                       /* Enqueue it to the orphan-reader-list */
  669.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  670.             ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  671.             AddTail((struct List*)&pb->pb_ReadOrphanList, (struct Node*)ios2);
  672.             ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  673.             ios2 = NULL;
  674.          }
  675.       break;
  676.  
  677.       case S2_GETGLOBALSTATS:
  678.          memcpy(ios2->ios2_StatData, &pb->pb_DevStats, sizeof(struct Sana2DeviceStats));
  679.       break;
  680.  
  681.       case S2_GETSPECIALSTATS:
  682.       {
  683.          struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  684.  
  685.          s2ssh->RecordCountSupplied = 0;
  686.          ios2->ios2_Req.io_Error = IOERR_NOCMD;
  687.       }
  688.       break;
  689.  
  690.       /* --------------- unsupported requests -------------------- */
  691.  
  692.          /* all standard commands we don't support */
  693.       case CMD_RESET:
  694.       case CMD_UPDATE:
  695.       case CMD_CLEAR:
  696.       case CMD_STOP:
  697.       case CMD_START:
  698.       case CMD_FLUSH:
  699.          ios2->ios2_Req.io_Error = IOERR_NOCMD;
  700.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  701.       break;
  702.  
  703.          /* other commands (SANA-2) we don't support */
  704.       /*case S2_ADDMULTICASTADDRESS:*/
  705.       /*case S2_DELMULTICASTADDRESS:*/
  706.       /*case S2_MULTICAST:*/
  707.       default:
  708.          ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  709.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  710.       break;
  711.    }
  712.  
  713.    if (ios2) DevTermIO(pb, ios2);
  714.  
  715.    return;
  716. }
  717. /*E*/
  718.  
  719.    /*
  720.    ** stop io-command
  721.    */
  722. /*F*/ extern ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  723. {
  724.    BOOL is;
  725.    LONG rc = 0;
  726.  
  727.    d(("cmd = %ld\n",ior->ios2_Req.io_Command));
  728.  
  729.    ObtainSemaphore(&pb->pb_WriteListSem);
  730.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_WriteList)) abort(pb,ior);
  731.    ReleaseSemaphore(&pb->pb_WriteListSem);
  732.    if (is) goto leave;
  733.  
  734.    ObtainSemaphore(&pb->pb_ReadListSem);
  735.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadList)) abort(pb,ior);
  736.    ReleaseSemaphore(&pb->pb_ReadListSem);
  737.    if (is) goto leave;
  738.  
  739.    ObtainSemaphore(&pb->pb_EventListSem);
  740.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_EventList)) abort(pb,ior);
  741.    ReleaseSemaphore(&pb->pb_EventListSem);
  742.    if (is) goto leave;
  743.  
  744.    ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  745.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadOrphanList)) abort(pb,ior);
  746.    ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  747.    if (is) goto leave;
  748.  
  749.    rc = -1;
  750.  
  751. leave:
  752.    return rc;
  753. }
  754. /*E*/
  755.  
  756.